home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_100 / 111_01 / usq.c < prev    next >
Text File  |  1985-08-19  |  8KB  |  289 lines

  1. /*
  2. HEADER:        ;
  3. TITLE:        Squeezer;
  4. VERSION:    1.5;
  5. DATE:        08/02/1981;
  6.  
  7. DESCRIPTION:    "USQ restores files which have been squeezed by the
  8.         SQ file compression utility program.  For compiling
  9.         and operating instructions, see the file SQUEEZER.DOC.";
  10.  
  11. KEYWORDS:    Data compression, squeeze, unsqueeze;
  12. SYSTEM:        CP/M-80;
  13. FILENAME:    USQ.C;
  14. SEE-ALSO:    SQ.C, FLS.C, SQUEEZER.DOC;
  15. AUTHORS:    Dick Greenlaw;
  16. COMPILERS:    BDS C;
  17. */
  18. /************************************************************************
  19.  
  20.  * Program to unsqueeze files formed by sq.com
  21.  *
  22.  * Useage:
  23.  *    USQ item ...
  24.  * where ... represents more (optional) items and
  25.  * "item" is either:
  26.  *    drive:        to change the output drive
  27.  *    file        input file
  28.  *    drive:file    input file
  29.  *    -count        Previewing feature: redirects output
  30.  *             files to standard output with parity stripped
  31.  *            and unprintables except CR, LF, TAB and  FF
  32.  *            converted to periods. Limits each file
  33.  *            to first count lines.
  34.  *            Defaults to console, but see below how
  35.  *            to capture all in one file for further
  36.  *            processing, such as by PIP.
  37.  *            Count defaults to a very high value.
  38.  *            No CRC check is performed when previewing.
  39.  *            Use drive: to cancel this.
  40.  *
  41.  *    -fcount        Same as -count except formfeed
  42.  *            appended to preview of each file.
  43.  *            Example: -f10.
  44.  *
  45.  * If no such items are given on the command line you will be
  46.  * prompted for commands (one at a time). An empty command
  47.  * terminates the program.
  48.  *
  49.  * USQ uses the dio package, so input and output can be redirected
  50.  * by special items on the command line such as:
  51.  *    <file        reads console input from file
  52.  *    >file        sends console output to file
  53.  *    +file        sends console output to console and file
  54.  * Also console output of another program using dio can be piped
  55.  * to the input of USQ or vice-versa. Example:
  56.  *    A>fls parameters |usq
  57.  * where fls might be a program that expands patterns like *.asm
  58.  * to a list of specific file names for usq to unsqueeze.
  59.  *
  60.  * The unsqueezed file name is recorded in the squeezed file.
  61.  *
  62.  * Examples:
  63.  *    A>USQ GRUMP.QQQ        writes on a:
  64.  *    A>USQ D:CRAP.XQZ    writes on A:
  65.  *    A>USQ B: D:CRAP.CQM    writes on B:
  66.  *    B>USQ X.AQ C: Y.BQ    writes X.?? on B: and Y.?? on C:
  67.  */
  68. /* CHANGE HISTORY:
  69.  * 1.3    Close inbuff to avoid exceeding maximum number of
  70.  *    open files. Includes rearranging error exits.
  71.  * 1.4    Add -count option to allow quick inspection of files.
  72.  * 1.5  Break up long lines of introductory text
  73.  * 1.5  -count no longer appends formfeed to preview of each file.
  74.  *    -fcount (-f10, -F10) does append formfeed.
  75.  */
  76.  
  77. #include <bdscio.h>
  78. #include <dio.h>
  79. #include "sqcom.h"
  80. #include "usq.h"
  81. #define VERSION "1.5   08/02/81"
  82. #define STDERR 4    /*Error output stream (always cxonsole) */
  83.  
  84. /* This must follow all include files */
  85. unsigned dispcnt;    /* How much of each file to preview */
  86. char    ffflag;        /* should formfeed separate preview from different files */
  87.  
  88. main(argc, argv)
  89. int argc;
  90. char *argv[];
  91. {
  92.     int i,c;
  93.     int getchar();        /* Directed io version */
  94.     char inparg[16];    /* parameter from input */
  95.  
  96.     dioinit(&argc, argv);    /* obey directed to args */
  97.  
  98.     dispcnt = 0;    /* Not in preview mode */
  99.  
  100.     fprintf(STDERR, "File unsqueezer version %s by\n\tRichard Greenlaw\n\t251 Colony Ct.\n\tGahanna, Ohio 43230\n", VERSION);
  101.     fprintf(STDERR, "Accepts redirection and pipes.\nOmit other parameters for help and prompt\n");
  102.  
  103.     /* Initialize output drive to default drive */
  104.     outdrv[0]  = '\0';
  105.     /* But prepare for a specific drive */
  106.     outdrv[1] = ':';
  107.     outdrv[2] = '\0';    /* string terminator */
  108.  
  109.     /* Process the parameters in order */
  110.     for(i = 1; i < argc; ++i)
  111.         obey(argv[i]);
  112.  
  113.     if(argc < 2) {
  114.         fprintf(STDERR, "Parameters are from command line or one-at-a-time from standard\ninput and are output drives and input file names. Empty to quit.\n");
  115.         do {
  116.             fprintf(STDERR, "\n*");
  117.             for(i = 0; i < 16; ++i) {
  118.                 if((c = getchar()) == EOF)
  119.                     c = '\n';    /* force empty (exit) command */
  120.                 if((inparg[i] = c) == '\n') {
  121.                     inparg[i] = '\0';
  122.                     break;
  123.                 }
  124.             }
  125.             if(inparg[0] != '\0')
  126.                 obey(inparg);
  127.         } while(inparg[0] != '\0');
  128.     }
  129.     dioflush();    /* clean up any directed io */
  130. }
  131.  
  132. obey(p)
  133. char *p;
  134. {
  135.     char *q;
  136.  
  137.     if(*p == '-') {
  138.         if(ffflag = (toupper(*(p+1)) == 'F'))
  139.             ++p;
  140.         /* Set number of lines of each file to view */
  141.         dispcnt = 65535;    /* default */
  142.         if(*(p+1))
  143.             if((dispcnt = atoi(p + 1)) == 0)
  144.                 fprintf(STDERR, "\nBAD COUNT %s", p + 1);
  145.         return;
  146.     }
  147.  
  148.     if(*(p + 1) == ':') {
  149.         /* Got a drive */
  150.         if(isalpha(*p)) {
  151.             if(*(p+2) == '\0') {
  152.                 /* Change output drive */
  153.                 dispcnt = 0;    /* cancel previewing */
  154.                 printf("\nOutput drive =%s",p);
  155.                 outdrv[0] = *p;
  156.                 return;
  157.             }
  158.         } else {
  159.             fprintf(STDERR, "\nERROR - Ignoring %s", p);
  160.             return;
  161.         }
  162.     }
  163.  
  164.     /* Check for ambiguous (wild-card) name */
  165.     for(q = p; *q != '\0'; ++q)
  166.         if(*q == '*' || *q == '?') {
  167.             fprintf(STDERR, "\nCan't accept ambiguous name %s", p);
  168.             return;
  169.         }
  170.  
  171.     unsqueeze(p);
  172. }
  173.  
  174.  
  175. unsqueeze(infile)
  176. char *infile;
  177. {
  178.     struct _buf inbuff, outbuff;    /* file buffers */
  179.     int i, c;
  180.     char cc;
  181.  
  182.     char *p;
  183.     unsigned filecrc;    /* checksum */
  184.     int numnodes;        /* size of decoding tree */
  185.     char outfile[16];    /* output file name */
  186.     unsigned linect;    /* count of number of lines previewed */
  187.  
  188.     if(fopen(infile, &inbuff) == ERROR) {
  189.         fprintf(STDERR, "Can't open %s\n", infile);
  190.         return;
  191.     }
  192.     /* Initialization */
  193.     linect = 0;
  194.     crc = 0;
  195.     init_cr();
  196.     init_huff();
  197.  
  198.     /* Process header */
  199.     if(getw(&inbuff) != RECOGNIZE) {
  200.         fprintf(STDERR, "%s is not a squeezed file\n", infile);
  201.         goto closein;
  202.     }
  203.  
  204.     filecrc = getw(&inbuff);
  205.  
  206.     /* Get original file name */
  207.     p = origname;    /* send it to array */
  208.     do {
  209.         *p = getc(&inbuff);
  210.     } while(*p++ != '\0');
  211.  
  212.     /* Combine with output drive */
  213.     outfile[0] = '\0';        /* empty */
  214.     strcat(outfile, outdrv);    /* drive */
  215.     strcat(outfile, origname);    /* name */
  216.  
  217.     printf("\n%s -> %s: ", infile, outfile);
  218.  
  219.  
  220.     numnodes = getw(&inbuff);
  221.  
  222.     if(numnodes < 0 || numnodes >= NUMVALS) {
  223.         fprintf(STDERR, "%s has invalid decode tree size\n", infile);
  224.         goto closein;
  225.     }
  226.  
  227.     /* Initialize for possible empty tree (SPEOF only) */
  228.     dnode[0].children[0] = -(SPEOF + 1);
  229.     dnode[0].children[1] = -(SPEOF + 1);
  230.  
  231.     /* Get decoding tree from file */
  232.     for(i = 0; i < numnodes; ++i) {
  233.         dnode[i].children[0] = getw(&inbuff);
  234.         dnode[i].children[1] = getw(&inbuff);
  235.     }
  236.  
  237.     if(dispcnt) {
  238.         /* Use standard output for previewing */
  239.         putchar('\n');
  240.         while(((c = getcr(&inbuff)) != EOF) && (linect < dispcnt)) {
  241.             cc = 0x7f & c;    /* strip parity */
  242.             if((cc < ' ') || (cc > '~'))
  243.                 /* Unprintable */
  244.                 switch(cc) {
  245.                 case '\r':    /* return */
  246.                     /* newline will generate CR-LF */
  247.                     goto next;
  248.                 case '\n':    /* newline */
  249.                     ++linect;
  250.                 case '\f':    /* formfeed */
  251.                 case '\t':    /* tab */
  252.                     break;
  253.                 default:
  254.                     cc = '.';
  255.                 }
  256.             putchar(cc);
  257.         next: ;
  258.         }
  259.         if(ffflag)
  260.             putchar('\f');    /* formfeed */
  261.     } else {
  262.         /* Create output file */
  263.         if(fcreat(outfile, &outbuff) == ERROR) {
  264.             fprintf(STDERR, "Can't create %s\n", outfile);
  265.             goto closeall;
  266.         }
  267.         /* Get translated output bytes and write file */
  268.         while((c = getcr(&inbuff)) != EOF) {
  269.             crc += c;
  270.             if((putc(c, &outbuff)) == ERROR) {
  271.                 fprintf(STDERR, "Write error in %s\n", outfile);
  272.                 goto closeall;
  273.             }
  274.         }
  275.  
  276.         if(filecrc != crc)
  277.             fprintf(STDERR, "ERROR - checksum error in %s\n", outfile);
  278.  
  279.  
  280.     closeall:
  281.         fflush(&outbuff);
  282.         fclose(&outbuff);
  283.     }
  284.  
  285. closein:
  286.     fclose(&inbuff);
  287. }
  288.  
  289.